package com.example.usermanagement.liuka.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.usermanagement.events.LiukaMessageApplicationEvent;
import com.example.usermanagement.events.LiukaStopApplicationEvent;
import com.example.usermanagement.exception.ObjectNotException;
import com.example.usermanagement.exception.ParamErrorException;
import com.example.usermanagement.liuka.mapper.FlowLogMapper;
import com.example.usermanagement.liuka.model.FlowLog;
import com.example.usermanagement.liuka.model.FlowPackage;
import com.example.usermanagement.liuka.model.FlowPackageUser;
import com.example.usermanagement.liuka.model.FlowUser;
import com.example.usermanagement.liuka.service.*;
import com.example.usermanagement.publisher.ApplicationPush;
import com.example.usermanagement.utils.LocaTimeToDateUtil;
import com.example.usermanagement.vo.FlowReportVO;
import com.example.usermanagement.vo.FlowUserShopVO;
import lombok.AllArgsConstructor;
import org.apache.catalina.core.ApplicationPushBuilder;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author yha
 * @ClassName
 * @description:TODO
 * @date 2024年09月10日
 * @version: 1.0.0
 */
@AllArgsConstructor
@Service
public class FlowLogServiceimpl extends ServiceImpl<FlowLogMapper, FlowLog> implements FlowLogService {

    private final FlowUserService flowUserService;
    private final FlowPackageService flowPackageService;
    private final FlowPackageUserService flowPackageUserService;
    private final ApplicationEventPublisher applicationPushBuilder;


    @Override
    public FlowLog addLog(Long packageId, Long flowUserId, BigDecimal flowSize,Long flowPackageUserId) throws ObjectNotException {
        FlowLog flowLog = getOne(Wrappers.lambdaQuery(new FlowLog())
                .eq(FlowLog::getPackageId,packageId)
                .eq(FlowLog::getFlowPackageUserId,flowPackageUserId)
                .eq(FlowLog::getFlowUserId,flowUserId).last(" limit 1")
                .orderByDesc(FlowLog::getId));

        //无数据新增
        FlowPackage flowPackage = flowPackageService.getById(packageId);
        if(Objects.isNull(flowPackage)){
            throw new ObjectNotException("套餐包不存在");
        }
        FlowUser flowUser = flowUserService.getById(flowUserId);
        if(Objects.isNull(flowUser)){
            throw new ObjectNotException("购买用户信息不存在");
        }
        if(Objects.isNull(flowLog)){


            BigDecimal cha = flowPackage.getFlowSize().subtract(flowSize);

            if(cha.compareTo(BigDecimal.ZERO)<0){
                cha = BigDecimal.ZERO;
            }
            flowLog = FlowLog.builder()
                    .flowSize(flowSize)
                    .flowPackageUserId(flowPackageUserId)
                    .sumFlowSize(flowPackage.getFlowSize())
                    .surplusFlowSize(cha)
                    .packageId(flowPackage.getId())
                    .flowUserId(flowUserId).build();
        }else{
            flowLog.setId(null);
            flowLog.setFlowSize(flowSize);
            BigDecimal cha = flowLog.getSurplusFlowSize().subtract(flowSize);
            flowLog.setSumFlowSize(flowLog.getSurplusFlowSize());
            flowLog.setSurplusFlowSize(cha);
            flowLog.setFlowPackageUserId(flowPackageUserId);
            if(cha.doubleValue()<0){
               cha = BigDecimal.ZERO;
               flowLog.setSurplusFlowSize(cha);
            }
        }

        //检测剩余流量
        BigDecimal sheng = flowLog.getSurplusFlowSize();
        BigDecimal sumSizwe = flowPackage.getFlowSize();
        BigDecimal z = sheng.divide(sumSizwe,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
        StringBuffer sf = new StringBuffer();
        if(z.intValue()<=20){

            sf.append("[用户]")
                    .append("手机号为:").append(flowUser.getPhone()).append(",").append("剩余流量低于").append("20").append("%");
        }
        if(z.intValue()<=80){
            sf.append("[用户]")
                    .append("手机号为:").append(flowUser.getPhone()).append(",").append("剩余流量低于").append("80").append("%");
        }
        if(z.intValue()==0){
            sf.append("[用户]")
                    .append("手机号为:").append(flowUser.getPhone()).append(",").append("流量已经用完");
        }
        applicationPushBuilder.publishEvent(new LiukaMessageApplicationEvent(this,flowUser.getPhone(),sf.toString()));

        save(flowLog);
        return flowLog;
    }


    @Override
    public void addFlow(Long flowUserId, BigDecimal flowSize) throws ObjectNotException, ParamErrorException {
        //获取 这个用户 购买的套餐包
        List<FlowPackageUser> data = flowPackageUserService.list(
                Wrappers.lambdaQuery(new FlowPackageUser())
                        .eq(FlowPackageUser::getFlowUserId,flowUserId)
                        .eq(FlowPackageUser::getEnable,1)
                        .le(FlowPackageUser::getShopTime, LocalDateTime.now())
                        .ge(FlowPackageUser::getEndTime,LocalDateTime.now())
                        .eq(FlowPackageUser::getStatus,1)
                        .orderByDesc(FlowPackageUser::getId)
        );

        //立即生效
        List<FlowPackageUser> list = data.parallelStream().filter(t->{
            return t.getType().equals(1);
        }).collect(Collectors.toList());

        if(list.size()<1) {

            //规则使用
            list = data.parallelStream()
                    .filter(t->{
                        return t.getType().equals(2);
                    }).sorted(Comparator.comparing(FlowPackageUser::getReadyMode).reversed())
                    .collect(Collectors.toList());
        }

        for (FlowPackageUser datum : list) {
            FlowLog flowLog = addLog(datum.getPackageId(), flowUserId, flowSize,datum.getId());
            Boolean next = true;
            if (flowLog.getSurplusFlowSize().compareTo(BigDecimal.ZERO)==0) {
                datum.setEnable(0);
                flowPackageUserService.updateById(datum);
                applicationPushBuilder.publishEvent(new LiukaStopApplicationEvent(this,datum.getId()));
                next = false;
            }
            if (next) {
                break;
            }
        }
        Long users = flowPackageUserService.count(
                Wrappers.lambdaQuery(new FlowPackageUser())
                        .eq(FlowPackageUser::getFlowUserId,flowUserId)
                        .eq(FlowPackageUser::getEnable,1)
                        .le(FlowPackageUser::getShopTime, LocalDateTime.now())
                        .ge(FlowPackageUser::getEndTime,LocalDateTime.now())
                        .orderByDesc(FlowPackageUser::getId)
        );
        if(users<1){
            FlowUser flowUser = flowUserService.getById(flowUserId);
            StringBuffer sf = new StringBuffer();
            sf.append("[用户]")
                    .append("手机号为:").append(flowUser.getPhone()).append(",")
                    .append("已经使用完所有套餐流量").append("即将准备关闭流量计算通道!");
            applicationPushBuilder.publishEvent(new LiukaMessageApplicationEvent(this,flowUser.getPhone(),sf.toString()));
            throw new ParamErrorException("套餐包内所有流量已经用完，已经关闭计算通道");
        }


    }

    @Override
    public FlowUserShopVO getDetail(Long id) throws ObjectNotException {
        FlowUser flowUser = flowUserService.getById(id);
        if(Objects.isNull(flowUser)){
            throw new ObjectNotException("购买用户信息不存在");
        }
        FlowUserShopVO shopVO = new FlowUserShopVO();
        shopVO.setId(flowUser.getId());
        shopVO.setName(flowUser.getName());
        shopVO.setPhone(flowUser.getPhone());

        List<FlowPackageUser> list = flowPackageUserService.list(
                Wrappers.lambdaQuery(new FlowPackageUser())
                        .eq(FlowPackageUser::getFlowUserId,flowUser.getId())
        );

        List<FlowUserShopVO.PackageVO> packageVOS = new ArrayList<>();
        BigDecimal sum = BigDecimal.ZERO;
        BigDecimal xiaohao = BigDecimal.ZERO;
        for (FlowPackageUser flowPackageUser : list) {

            FlowPackage flowPackage = flowPackageService.getById(flowPackageUser.getPackageId());
            sum = sum.add(flowPackageUser.getFlowSize());

            BigDecimal sheng = BigDecimal.ZERO;
            List<FlowLog> flowLogs =list(Wrappers.lambdaQuery(new FlowLog())
                    .eq(FlowLog::getFlowUserId,flowUser.getId())
                    .eq(FlowLog::getFlowPackageUserId,flowPackageUser.getId()));
            if(Objects.nonNull(flowLogs)&&flowLogs.size()>0){
                for (FlowLog flowLog : flowLogs) {
                    xiaohao = xiaohao.add(flowLog.getFlowSize());
                    sheng = sheng.add(flowLog.getFlowSize());

                }
            }

            FlowUserShopVO.PackageVO packageVO = new FlowUserShopVO.PackageVO();
            packageVO.setPackageName(flowPackage.getPackageName());
            packageVO.setShopTime(LocaTimeToDateUtil.localDateTimeToDate(flowPackageUser.getShopTime()));
            packageVO.setStatus(flowPackageUser.getStatus());
            packageVO.setSurplusFlowSize(sum.subtract(sheng).compareTo(BigDecimal.ZERO)<=0?BigDecimal.ZERO:sum.subtract(sheng));
            packageVOS.add(packageVO);
        }
        shopVO.setSuprSize(sum.subtract(xiaohao).compareTo(BigDecimal.ZERO)<=0?BigDecimal.ZERO:xiaohao.subtract(sum));

        shopVO.setPackageVOS(packageVOS);
        return shopVO;
    }

    @Override
    public List<FlowReportVO> reportList() {
        return baseMapper.reportList();
    }
}
